package asset

import (
	"context"
	"github.com/gogf/gf/v2/errors/gerror"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/shopspring/decimal"
	"grpc-common/api/user/asset"
	"user/internal/dao"
	"user/internal/model/entity"
)

// Asset的业务逻辑层
type AssetLogic struct {
}

func NewAssetLogic() *AssetLogic {
	return &AssetLogic{}
}

// 查询用户钱包信息
func (l *AssetLogic) FindWalletBySymbol(ctx context.Context, req *asset.AssetReq) (res *asset.MemberWallet, err error) {
	//查找wallet的信息
	wallet, err := l.findWallet(ctx, req.UserId, req.CoinId)
	if err != nil {
		return &asset.MemberWallet{}, err
	}
	//查询coin的信息
	coin, err := l.findCoin(ctx, req.CoinId)
	if err != nil {
		return &asset.MemberWallet{}, err
	}
	return &asset.MemberWallet{
		Id:             wallet.Id,
		Balance:        wallet.Balance,
		FrozenBalance:  wallet.FrozenBalance,
		ReleaseBalance: wallet.ReleaseBalance,
		IsLock:         int32(wallet.IsLock),
		UserId:         wallet.UserId,
		Coin: &asset.Coin{
			Id:   coin.Id,
			Name: coin.Name,
		},
	}, nil
}

// 充值钱包
func (l *AssetLogic) ChargeWalletBySymbol(ctx context.Context, req *asset.AssetReqBalance) (res *asset.MemberWallet, err error) {
	//find wallet
	wallet, err := l.findWallet(ctx, req.UserId, req.CoinId)
	if err != nil {
		return &asset.MemberWallet{}, err
	}
	//change wallet
	currentBalance := wallet.Balance
	version := wallet.Version
	fee := req.Fee
	if currentBalance <= fee {
		return &asset.MemberWallet{}, gerror.New("余额不足，无法扣减")
	}
	currentBalanceCal := decimal.NewFromFloat(currentBalance)
	currentFee := decimal.NewFromFloat(fee)
	var newBalanceCal = decimal.NewFromFloat(0)
	if "+" == req.Op {
		newBalanceCal = currentBalanceCal.Add(currentFee)
	} else {
		newBalanceCal = currentBalanceCal.Sub(currentFee)
	}

	data := g.Map{
		"balance": newBalanceCal,
		"version": version + 1,
	}
	result, err := dao.Wallet.Ctx(ctx).Where(req).
		Where(dao.Wallet.Columns().UserId, req.UserId).
		Where(dao.Wallet.Columns().CoinId, req.CoinId).
		Where(dao.Wallet.Columns().Version, version). //版本号
		Data(data).Update()
	affected, _ := result.RowsAffected()
	g.Log().Printf(ctx, "影响行数:%d", affected)
	if err != nil {
		return &asset.MemberWallet{}, err
	}
	//返回钱包信息
	newWallet, err := l.findWallet(ctx, req.UserId, req.CoinId)
	if err != nil {
		return &asset.MemberWallet{}, err
	}
	//coin信息
	coin, err := l.findCoin(ctx, req.CoinId)
	if err != nil {
		return &asset.MemberWallet{}, err
	}
	return &asset.MemberWallet{
		Id:             newWallet.Id,
		Balance:        newWallet.Balance,
		FrozenBalance:  newWallet.FrozenBalance,
		ReleaseBalance: newWallet.ReleaseBalance,
		IsLock:         int32(newWallet.IsLock),
		UserId:         newWallet.UserId,
		Coin: &asset.Coin{
			Id:   coin.Id,
			Name: coin.Name,
		},
	}, nil
}

// 创建钱包
func (l *AssetLogic) InsertWallet(ctx context.Context, req *asset.InsertWalletReq) (*asset.MemberWallet, error) {
	//查询coin
	coin, err := l.findCoin(ctx, req.CoinId)
	if err != nil {
		return &asset.MemberWallet{}, err
	}
	//插入到wallet
	g2 := g.Map{
		"user_id": req.UserId,
		"coin_id": req.CoinId,
	}
	id, err := dao.Wallet.Ctx(ctx).InsertAndGetId(g2)
	if err != nil {
		return &asset.MemberWallet{}, err
	}
	//返回结果
	return &asset.MemberWallet{
		Id:             id,
		Balance:        0,
		FrozenBalance:  0,
		ReleaseBalance: 0,
		IsLock:         0,
		UserId:         req.UserId,
		Coin: &asset.Coin{
			Id:   req.CoinId,
			Name: coin.Name,
		},
	}, nil
}

// 查找钱包Wallet
func (l *AssetLogic) findWallet(ctx context.Context, userId int64, coinId int64) (*entity.Wallet, error) {
	wallet := &entity.Wallet{}
	err := dao.Wallet.Ctx(ctx).
		Where(dao.Wallet.Columns().UserId, userId).
		Where(dao.Wallet.Columns().CoinId, coinId).
		Scan(wallet)
	return wallet, err
}

// 查找Coin
func (l *AssetLogic) findCoin(ctx context.Context, coinId int64) (*entity.Coin, error) {
	coin := &entity.Coin{}
	err := dao.Coin.Ctx(ctx).Where(dao.Coin.Columns().Id, coinId).Scan(coin)
	return coin, err
}
